package com.flx.dis.registry.zk.service.impl;

import com.flx.dis.registry.zk.server.ZkServer;
import com.flx.dis.registry.zk.service.MonitorService;
import lombok.extern.slf4j.Slf4j;
import org.I0Itec.zkclient.ZkClient;
import org.hyperic.sigar.CpuPerc;
import org.hyperic.sigar.Mem;
import org.hyperic.sigar.Sigar;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.net.InetAddress;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @Author Fenglixiong
 * @Create 2022/4/19 13:26
 * @Description
 **/
@Slf4j
@Service
public class MonitorServiceImpl implements MonitorService {

    @Autowired
    private ZkServer zkServer;

    //跟节点
    private final static String rootPath = "/server-manager";
    //临时序号节点
    private static String serverPath = rootPath+"/server";
    //当前路径节点
    private String currentPath;

    /**
     * 启动监控程序
     */
    public void startMonitor() throws Exception {
        ZkClient zkClient = zkServer.getZkClient();
        if(zkClient==null){
            return;
        }
        System.out.println("zk监控开始运行...");

        //创建跟节点
        buildRoot(zkClient);
        //创建服务节点
        createServerNode(zkClient);
        //创建线程定时上报信息
        Thread monitorThread = new Thread(()->{
            while (true) {
                try {
                    Thread.sleep(5000);
                    updateServerNode(zkClient);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"monitorZK");
        monitorThread.setDaemon(true);
        monitorThread.start();
    }

    /**
     * 创建跟节点
     */
    public void buildRoot(ZkClient zkClient){
        if(!zkClient.exists(rootPath)){
            zkClient.createPersistent(rootPath);
            log.info("==============>创建跟节点成功,path = {}",rootPath);
        }
    }

    /**
     * 创建服务节点
     */
    public void createServerNode(ZkClient zkClient)throws Exception{
        String serverInfo = getServerInfo();
        currentPath = zkClient.createEphemeralSequential(serverPath,serverInfo);
        log.info("==================>创建服务节点成功：path = {},value = {}",currentPath,serverInfo);
    }

    /**
     * 修改服务节点
     */
    public void updateServerNode(ZkClient zkClient)throws Exception{
        String serverInfo = getServerInfo();
        zkClient.writeData(currentPath,serverInfo);
        log.info("==================>修改服务节点成功：path = {},value = {}",currentPath,serverInfo);
    }

    /**
     * 获取服务器信息
     * @return cpu，内存，磁盘信息
     */
    private static String getServerInfo() throws Exception {
        Map<String,Object> serverMap = new LinkedHashMap<>();
        serverMap.put("lastUpdateTime",System.currentTimeMillis());
        serverMap.put("ip",getLocalIp());
        serverMap.put("cpu",getCpu());
        serverMap.put("usedMemory",getUsedMemory());
        serverMap.put("totalMemory",getTotalMemory());
        return serverMap.toString();
    }

    /**
     * 获取当前服务机器的IP地址
     * @return 返回IP
     */
    private static String getLocalIp(){
        InetAddress address = null;
        try{
            address = InetAddress.getLocalHost();
        }catch (Exception e){
            log.error("获取当前IP地址失败！");
            throw new RuntimeException(e);
        }
        return address.getHostAddress();
    }

    private static String getCpu()throws Exception{
        Sigar sigar = new Sigar();
        CpuPerc[] cpuList = sigar.getCpuPercList();
        return CpuPerc.format(cpuList[0].getCombined());
    }

    private static double getUsedMemory()throws Exception{
        Sigar sigar = new Sigar();
        Mem mem = sigar.getMem();
        return (double)mem.getUsed()/(1024*1024);
    }

    private static double getTotalMemory()throws Exception{
        Sigar sigar = new Sigar();
        Mem mem = sigar.getMem();
        return (double)mem.getTotal()/(1024*1024);
    }

}
